<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="ColorVertexShader" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    uniform float u_PointSize;
    uniform mat4 u_ModelM4;
    uniform mat4 u_PvM4;
    void main(){
        gl_Position = u_PvM4 * u_ModelM4 * a_Position;
        gl_PointSize = u_PointSize;
    }
</script>
<script id="ColorFragmentShader" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec4 u_Color;
    void main(){
        gl_FragColor = u_Color;
    }
</script>
<script type="module">
    import { Matrix4, Vector3, Color, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'

    import Geo from '../js/Poly/Geo.js'
    import Mat from '../js/Poly/Mat.js'
    import Obj3D from '../js/Poly/Obj3D.js'
    import Scene from '../js/Poly/Scene.js'



    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight - 4;

    const gl = canvas.getContext("webgl", { antialias: true, });

    // gl.enable(gl.DEPTH_TEST);//开始背景遮挡会频闪
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    //#endregion


    let program = CreateProgram(gl,
        document.querySelector('#ColorVertexShader').innerText,
        document.querySelector('#ColorFragmentShader').innerText);


    const scene = new Scene({ gl: gl });

    const pvM4 = new Matrix4();
    const modelM4 = new Matrix4();

    const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 1, 20);
    const cameraController = new CameraController({
        canvas,
        camera,
        pvMatrix: pvM4,
        rendEvent: draw,
    });

    const nodeLength = 0.5;
    const nodeArr = [
        -nodeLength, nodeLength,
        -nodeLength, -nodeLength,
        nodeLength, -nodeLength,
        nodeLength, nodeLength,
    ];

    const elementArr = [
        0, 1, 2,
        0, 2, 3,
    ];

    const objArr = [];


    let obj01 = new Obj3D({
        geo: new Geo({
            data: {
                'a_Position': { size: 2, array: new Float32Array(nodeArr) },
            },
            element: {
                array: new Uint8Array(elementArr)
            }
        }),
        mat: new Mat({
            program: program,
            mode: ['TRIANGLES'],
            data: {
                'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                'u_Color': { type: 'uniform4fv', value: [1, 1, 1, 1] },
            },
        }),
    });
    objArr.push(obj01);

    const p = [0, 0];
    let pObj = new Obj3D({
        geo: new Geo({
            data: {
                'a_Position': { size: 2, array: new Float32Array(p) },
            },
        }),
        mat: new Mat({
            program: CreateProgram(gl,
                document.querySelector('#ColorVertexShader').innerText,
                document.querySelector('#ColorFragmentShader').innerText),
            mode: ['POINTS'],
            data: {
                'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                'u_Color': { type: 'uniform4fv', value: [1, 0, 0, 1] },
                'u_PointSize': { type: 'uniform1f', value: 30 },
            },
        }),
    });

    const line = [];
    let lineObj = new Obj3D({
        geo: new Geo({
            data: {
                'a_Position': { size: 2, array: new Float32Array(line) },
            },
            element: {
                array: new Uint8Array([0, 1, 1, 2, 2, 3, 3, 0]),//目前先写死吧
            }
        }),
        mat: new Mat({
            program: CreateProgram(gl,
                document.querySelector('#ColorVertexShader').innerText,
                document.querySelector('#ColorFragmentShader').innerText),
            mode: ['POINTS', 'LINES'],
            data: {
                'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                'u_Color': { type: 'uniform4fv', value: [1, 0, 1, 0] },
                'u_PointSize': { type: 'uniform1f', value: 10 },
            },
        }),
    });

    scene.add(obj01);
    // scene.add(pObj);
    scene.add(lineObj);

    scene.draw();

    canvas.addEventListener('mousemove', function (event) {
        const { clientX, clientY } = event;

        const [x, y] = cssToGl(clientX, clientY);
        p[0] = x;
        p[1] = y;
        pObj.setAttrib('a_Position', { array: new Float32Array(p) })
        // console.log(x, y)

        let isIn = null;

        //判断鼠标是否进入了某个图形
        for (let i = 0; i < objArr.length; i++) {
            let objNodes = objArr[i].geo.data['a_Position'].array;
            let objElements = objArr[i].geo.element.array;

            if (inObj(objNodes, objElements)) {
                isIn = objNodes;
                break;
            }
        }


        if (isIn) {
            lineObj.setAttrib('a_Position', { array: isIn });
            lineObj.setUniform('u_Color', { value: [1, 0, 1, 1] });
        } else {
            lineObj.setUniform('u_Color', { value: [1, 0, 1, 0] });
        }

        draw();
    })

    function inObj(objNodes, objElements) {
        for (let j = 0; j < objElements.length; j += 3) {
            let TRIANGLES = [];
            let nodeindex = objElements[j];
            TRIANGLES.push({ x: objNodes[nodeindex * 2], y: objNodes[nodeindex * 2 + 1] });
            nodeindex = objElements[j + 1];
            TRIANGLES.push({ x: objNodes[nodeindex * 2], y: objNodes[nodeindex * 2 + 1] });
            nodeindex = objElements[j + 2];
            TRIANGLES.push({ x: objNodes[nodeindex * 2], y: objNodes[nodeindex * 2 + 1] });

            if (lib.inTriangle(
                { x: p[0], y: p[1] },
                TRIANGLES)) {
                return true;
                break;
            }
        }
        return false;
    }

    function cssToGl(x, y) {
        const [hx, hy] = [canvas.width / 2, canvas.height / 2];
        //裁剪空间位, 及屏幕位
        const cp = new Vector3((x - hx) / hx, -(y - hy) / hy, 0);
        //世界坐标位置, 即裁剪空间位 * 投影矩阵的逆坐标
        const p = cp.applyMatrix4(pvM4.clone().invert())
        return p;
    }

    function draw() {
        // scene.setUniform('u_PvM4', { value: pvM4.elements });
        scene.draw();
    }
    // let ret = lib.inTriangle(
    //     { x: p[0], y: p[1] },
    //     [
    //         { x: nodeArr[0], y: nodeArr[1] },
    //         { x: nodeArr[2], y: nodeArr[3] },
    //         { x: nodeArr[4], y: nodeArr[5] },
    //     ]);

</script>

</html>